package org.example.yolodemo.controller;

import org.example.yolodemo.util.VideosUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.stream.Collectors;

@Controller
@RequestMapping("/video")
public class VideosController {

    @Value("${video.upload.dir}")
    private String uploadDir;

    @Value("${video.model.path}")
    private String modelPath;

    @RequestMapping("/uploadVideo")
    public String uploadVideo(){
        return "video";
    }

    // 确保上传目录存在
    @PostConstruct
    public void init() {
        try {
            Path path = Paths.get(uploadDir);
            if (!Files.exists(path)) {
                Files.createDirectories(path);
            }
            // 确保识别结果目录存在
            path = Paths.get(uploadDir + "processed/");
            if (!Files.exists(path)) {
                Files.createDirectories(path);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @GetMapping
    public String videoPage(Model model) {
        return "video";
    }

    @PostMapping("/upload")
    public String uploadVideo(@RequestParam("file") MultipartFile file, Model model) {
        if (file.isEmpty()) {
            model.addAttribute("message", "请选择视频文件");
            return "video";
        }

        try {
            // 生成唯一文件名
            String originalFilename = file.getOriginalFilename();
            String fileExtension = originalFilename.substring(originalFilename.lastIndexOf('.'));
            String filename = UUID.randomUUID().toString() + fileExtension;

            // 保存原始视频
            Path targetLocation = Paths.get(uploadDir, filename);
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

            model.addAttribute("originalVideoPath", "/uploads/videos/" + filename);
            model.addAttribute("originalFilename", originalFilename);
            model.addAttribute("message", "视频上传成功");

            return "video";
        } catch (IOException e) {
            model.addAttribute("message", "上传失败: " + e.getMessage());
            return "video";
        }
    }

    @PostMapping("/process")
    @ResponseBody
    public Map<String, Object> processVideo(@RequestParam("videoPath") String videoPath) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", false);

        try {
            // 从URL路径中提取文件名
            String filename = videoPath.substring(videoPath.lastIndexOf('/') + 1);
            
            // 构建原始视频路径
            Path originalPath = Paths.get(uploadDir, filename);
            System.out.println("原始视频路径: " + originalPath);

            if (!Files.exists(originalPath)) {
                result.put("message", "原始视频不存在");
                return result;
            }

            // 构建处理后视频路径
            String processedFilename = filename.substring(0, filename.lastIndexOf('.')) + "_processed" + filename.substring(filename.lastIndexOf('.'));
            Path processedPath = Paths.get(uploadDir, "processed", processedFilename);
            System.out.println("处理后视频路径: " + processedPath);

            // 确保processed目录存在
            Files.createDirectories(processedPath.getParent());

            // 加载ONNX模型
            try {
                String modelFullPath = VideosUtil.getModelPath(modelPath);
                System.out.println("正在加载模型: " + modelFullPath);
                VideosUtil.load(modelFullPath);
                System.out.println("模型加载成功");
            } catch (Exception e) {
                System.err.println("模型加载失败: " + e.getMessage());
                e.printStackTrace();
                result.put("message", "模型加载失败: " + e.getMessage());
                return result;
            }

            // 处理视频
            Map<String, Object> processResult = VideosUtil.processVideo(originalPath.toString(), processedPath.toString());

            if ((boolean) processResult.get("success")) {
                result.put("success", true);
                result.put("message", "视频处理完成");
                result.put("processedVideoPath", "/uploads/videos/processed/" + processedFilename);
                result.put("processingTime", processResult.get("processingTimeMs"));
                result.put("framesProcessed", processResult.get("processedFrames"));
            } else {
                result.put("message", "视频处理失败: " + processResult.get("message"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            result.put("message", "处理过程中发生错误: " + e.getMessage());
        }

        return result;
    }

    @GetMapping("/view/{filename:.+}")
    public ResponseEntity<Resource> viewVideo(@PathVariable String filename, HttpServletRequest request) {
        try {
            Path path = Paths.get(uploadDir, filename);
            System.out.println("视频文件路径: " + path);

            Resource resource = new UrlResource(path.toUri());
            if (resource.exists() && resource.isReadable()) {
                String contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
                if (contentType == null) {
                    contentType = "application/octet-stream";
                }

                return ResponseEntity.ok()
                        .contentType(MediaType.parseMediaType(contentType))
                        .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + resource.getFilename() + "\"")
                        .body(resource);
            } else {
                System.out.println("视频文件不存在或不可读: " + path);
                return ResponseEntity.notFound().build();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("访问视频文件出错: " + e.getMessage());
            return ResponseEntity.badRequest().build();
        }
    }

    @GetMapping("/view/processed/{filename:.+}")
    public ResponseEntity<Resource> viewProcessedVideo(@PathVariable String filename, HttpServletRequest request) {
        try {
            Path path = Paths.get(uploadDir, "processed", filename);
            System.out.println("处理后视频文件路径: " + path);

            Resource resource = new UrlResource(path.toUri());
            if (resource.exists() && resource.isReadable()) {
                String contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
                if (contentType == null) {
                    contentType = "application/octet-stream";
                }

                return ResponseEntity.ok()
                        .contentType(MediaType.parseMediaType(contentType))
                        .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + resource.getFilename() + "\"")
                        .body(resource);
            } else {
                System.out.println("处理后视频文件不存在或不可读: " + path);
                return ResponseEntity.notFound().build();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("访问处理后视频文件出错: " + e.getMessage());
            return ResponseEntity.badRequest().build();
        }
    }

    @GetMapping("/list")
    @ResponseBody
    public Map<String, Object> listVideos() {
        Map<String, Object> result = new HashMap<>();
        result.put("videos", new ArrayList<>());

        try {
            // 获取原始视频列表
            File uploadDirFile = new File(uploadDir);
            if (uploadDirFile.exists() && uploadDirFile.isDirectory()) {
                List<Map<String, String>> videoList = Arrays.stream(uploadDirFile.listFiles())
                        .filter(f -> f.getName().endsWith(".mp4") || f.getName().endsWith(".avi") || f.getName().endsWith(".mkv"))
                        .map(f -> {
                            Map<String, String> video = new HashMap<>();
                            video.put("name", f.getName());
                            video.put("path", "/video/view/" + f.getName());
                            video.put("processedPath", "/video/view/processed/" + f.getName().replaceFirst("\\.[^.]+$", "_processed$0"));
                            video.put("size", formatFileSize(f.length()));
                            return video;
                        })
                        .collect(Collectors.toList());

                result.put("videos", videoList);
                result.put("success", true);
            }
        } catch (Exception e) {
            e.printStackTrace();
            result.put("message", "获取视频列表失败: " + e.getMessage());
        }

        return result;
    }

    private String formatFileSize(long bytes) {
        if (bytes < 1024) return bytes + " B";
        int exp = (int) (Math.log(bytes) / Math.log(1024));
        String pre = "KMGTPE".charAt(exp-1) + "";
        return String.format("%.2f %sB", bytes / Math.pow(1024, exp), pre);
    }
}